#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <iostream>

class Matrix
{
public:
  Matrix( int n, int m );
  
  void clear();
  
  void print( std::ostream& out = std::cout );
  
  static Matrix generate( int size );
  static Matrix generateL( int size );
  static Matrix generateU( int size );
  static Matrix generateIdentity( int size );
  static Matrix load( const char* filename );
  
  Matrix mul( Matrix matrix );
  void mul( Matrix matrix, Matrix *result );
  
  Matrix copy();
  void copy( Matrix *result, int yOffset=0, int xOffset=0 );
  Matrix submatrix( int xOffset, int yOffset, int xSize, int ySize );
  
  int N();
  int M();
  
  void doLU( Matrix lMatrix );
  void doLUBlock( Matrix lMatrix );
  
private:
  
  void solveSystemRight( Matrix lMatrix );
  void solveSystemLeft( Matrix uMatrix );
  
  void doLUStep( Matrix lMatrix, int baseLine=0 );
  void doLUBlockStep( Matrix lMatrix, int offset=0 );
  
  void solveSystemLeftStep( Matrix uMatrix, int offset=0 );
  
  float *_values;
  int _n;
  int _m;
  
};

#endif